package com.example.android.google;

import java.io.*;
import java.util.*;
import com.google.android.maps.MapActivity;
import android.widget.*;
import com.google.android.maps.*;
import android.app.*;
import android.content.*;
import android.graphics.*;
import android.graphics.drawable.*;
import android.location.*;
import android.media.*;
import android.net.Uri;
import android.os.Bundle;
import android.view.*;
import android.view.View.*;

public class AlarmLocationActivity extends MapActivity {
	/*
	 * variables used in attempt to alarm protected static final int ALARM_BREAK
	 * = 10; protected static final String STORAGE_FILE = "Location_Stores.txt";
	 */

	// global variables
	private MapView mv;
	private MapController mc;
	private GeoPoint gp, currentPos;
	private AlarmLocationOverlay alo;
	private Dialog dialog;
	private boolean mark = false, edit = false, lock = false, gps = false,
			triedGPS = false;
	private LocationManager locationManager;
	private EditText title, range;
	private CheckBox alarmBox;
	private Button delete;
	private int tap_int;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		// get map view information
		mv = (MapView) findViewById(R.id.mapview1);
		mv.setBuiltInZoomControls(true);
		mc = mv.getController();

		// add location alarm marking overlay
		Drawable marker = getResources().getDrawable(R.drawable.red_dot);
		marker.setBounds(0, marker.getIntrinsicHeight(),
				marker.getIntrinsicWidth(), 0);
		List<Overlay> listOfOverlays = mv.getOverlays();
		listOfOverlays.clear();

		alo = new AlarmLocationOverlay(marker);
		listOfOverlays.add(alo);

		/*
		 * attempted to get stored locations, not working in time File itemStore
		 * = new File(this.getFilesDir(), STORAGE_FILE); if (itemStore.exists())
		 * { try { Scanner scan = new Scanner(itemStore); while
		 * (scan.hasNextLine()) { Scanner info = new Scanner(scan.nextLine());
		 * mio.addItem(info.nextInt(), new GeoPoint((int) (info.nextDouble() *
		 * 1E6), (int) (info.nextDouble() * 1E6)), info .next(),
		 * info.nextDouble(), info .nextBoolean()); } } catch (Exception e) {
		 * Toast.makeText(getApplicationContext(), e.getMessage(),
		 * Toast.LENGTH_SHORT).show(); } }
		 */

		// add current position marking overlay if available
		if (hasGPSDevice(this)) {
			Location location = locationManager
					.getLastKnownLocation(LocationManager.GPS_PROVIDER);
			LocationListener mlocListener = new MyLocationListener();
			locationManager.requestLocationUpdates(
					LocationManager.GPS_PROVIDER, 0, 0, mlocListener);

			double geolat = location.getLatitude() * 1E6;
			double geolong = location.getLongitude() * 1E6;
			currentPos = new GeoPoint((int) (geolat), (int) (geolong));
			CurrentLocOverlay locOverlay = new CurrentLocOverlay();
			listOfOverlays.add(locOverlay);
		} else {
			// get Pittsburgh if not
			currentPos = new GeoPoint((int) (40.4406 * 1E6),
					(int) (-79.9961 * 1E6));
		}

		mc.setZoom(14);
		mc.animateTo(currentPos);
		mv.invalidate();

		// build alarm location dialog box
		dialog = new Dialog(this);
		dialog.setTitle("Location Information");
		dialog.setContentView(R.layout.location_dialog);

		title = (EditText) dialog.findViewById(R.id.titleField);
		range = (EditText) dialog.findViewById(R.id.rangeField);
		alarmBox = (CheckBox) dialog.findViewById(R.id.alarmBox);
		Button finish = (Button) dialog.findViewById(R.id.finishButton);
		finish.setOnClickListener(new OnClickListener() {
			public void onClick(View arg0) {
				// clicked finish, get information, check fields, add to overlay
				String t = title.getText().toString().trim();
				double r = Double
						.parseDouble(range.getText().toString().trim());
				boolean alrm = alarmBox.isChecked();
				if (!t.contains(" ")) {
					if (mark) {
						alo.addItem(gp, t, r, alrm);
					} else if (edit) {
						alo.createItem(tap_int).setTitle(t);
						alo.createItem(tap_int).setRange(r);
						alo.createItem(tap_int).setAlarm(alrm);
					}
					mv.invalidate();
					/*
					 * alarm setting code, future use Calendar cal =
					 * Calendar.getInstance(); cal.add(Calendar.SECOND,
					 * ALARM_BREAK);
					 * 
					 * Intent intent = new Intent(AlarmLocationActivity.this,
					 * AlarmReceiver.class); PendingIntent pendingIntent =
					 * PendingIntent.getBroadcast( AlarmLocationActivity.this,
					 * 12345, intent, PendingIntent.FLAG_CANCEL_CURRENT);
					 * AlarmManager am = (AlarmManager)
					 * getSystemService(Activity.ALARM_SERVICE);
					 * am.setRepeating(AlarmManager.RTC_WAKEUP,
					 * cal.getTimeInMillis(), ALARM_BREAK * 1000,
					 * pendingIntent); Toast.makeText(getApplicationContext(),
					 * "Alarm set", Toast.LENGTH_SHORT).show();
					 */
					dialog.dismiss();
				} else {
					Toast.makeText(getApplicationContext(),
							"Title cannot contain spaces", Toast.LENGTH_SHORT)
							.show();
				}
			}
		});
		Button cancel = (Button) dialog.findViewById(R.id.cancelButton);
		cancel.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				// cancel button hit, close dialog
				dialog.dismiss();
			}
		});
		delete = (Button) dialog.findViewById(R.id.deleteButton);
		delete.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				// delete button hit, remove marker from overlay
				alo.remove(tap_int);
				mv.invalidate();
				dialog.dismiss();
			}
		});
	}

	/*
	 * file saving code, not workinng in time protected void
	 * onSaveInstanceState(Bundle outState) { File itemStore = new
	 * File(this.getFilesDir(), STORAGE_FILE); try { PrintWriter out = new
	 * PrintWriter(new BufferedWriter( new FileWriter(itemStore)));
	 * 
	 * for (int i = 0; i < mio.size(); i++) { AlarmOverlayItem item =
	 * mio.createItem(i); String str = item.getID() + " "; str += ((double)
	 * item.getPoint().getLatitudeE6()) / 1E6 + " "; str += ((double)
	 * item.getPoint().getLongitudeE6()) / 1E6 + " "; str += item.getTitle() +
	 * " "; str += item.getRange() + " "; str += item.getAlarm();
	 * 
	 * out.println(str); }
	 * 
	 * out.close(); } catch (Exception e) {
	 * Toast.makeText(getApplicationContext(), e.getMessage(),
	 * Toast.LENGTH_SHORT).show(); } }
	 */

	// toggle mark boolean when button is clicked and turn off edit button
	public void onMarkClicked(View view) {
		mark = ((ToggleButton) view).isChecked();
		if (mark) {
			ToggleButton editBut = (ToggleButton) findViewById(R.id.editbutton);
			editBut.setChecked(false);
			edit = false;
		}
	}

	// toggle edit boolean when button is clicked and turn off mark button
	public void onEditClicked(View view) {
		edit = ((ToggleButton) view).isChecked();
		if (edit) {
			ToggleButton markBut = (ToggleButton) findViewById(R.id.markbutton);
			markBut.setChecked(false);
			mark = false;
		}
	}

	// toggle lock boolean when button is clicked
	public void onLockClicked(View view) {
		lock = ((ToggleButton) view).isChecked();
	}

	@Override
	protected boolean isRouteDisplayed() {
		return false;
	}

	// get location updates from gps, set off alarm if in range of alarm
	// location
	public class MyLocationListener implements LocationListener {
		private MediaPlayer mMediaPlayer;

		// location has changed
		public void onLocationChanged(Location arg0) {
			int i = 0;
			Location mark_location = new Location("");
			ArrayList<String> alarm_titles = new ArrayList<String>();
			AlarmOverlayItem temp;

			// update current location
			currentPos = new GeoPoint((int) (arg0.getLatitude() * 1E6),
					(int) (arg0.getLongitude() * 1E6));

			for (i = 0; i < alo.size(); i++) {
				// check distance to active alarms
				temp = alo.createItem(i);
				if (temp.getAlarm()) {
					mark_location.setLatitude(((double) temp.getPoint()
							.getLatitudeE6()) / 1E6);
					mark_location.setLongitude(((double) temp.getPoint()
							.getLongitudeE6()) / 1E6);

					if (mark_location.distanceTo(arg0) < temp.getRange()) {
						alarm_titles.add(temp.getTitle());
						temp.setAlarm(false);
					}
				}
			}

			if (alarm_titles.size() > 0) {
				// set off alarm and dialog box if any are close enough
				AlertDialog.Builder builder = new AlertDialog.Builder(
						AlarmLocationActivity.this);
				builder.setTitle("Alarm Alert!!");

				String str = "";
				for (i = 0; i < alarm_titles.size() - 1; i++) {
					str += alarm_titles.get(i) + ", ";
				}
				str += alarm_titles.get(i) + " alarm(s) are going off!!";

				builder.setMessage(str);
				builder.setPositiveButton("Ok",
						new DialogInterface.OnClickListener() {
							public void onClick(DialogInterface arg0, int arg1) {
								mMediaPlayer.stop();
								arg0.dismiss();
							}
						});
				AlertDialog alarmConfirm = builder.create();
				playSound(AlarmLocationActivity.this, getAlarmUri());
				alarmConfirm.show();
			}

			if (lock) {
				// update to current location if lock is on
				mc.animateTo(currentPos);
				mv.invalidate();
			}
		}

		public void onProviderDisabled(String arg0) {
			gps = false;
		}

		public void onProviderEnabled(String arg0) {
			gps = true;
		}

		public void onStatusChanged(String arg0, int arg1, Bundle arg2) {

		}

		// find and play alarm sound
		private void playSound(Context context, Uri alert) {
			mMediaPlayer = new MediaPlayer();
			try {
				mMediaPlayer.setDataSource(context, alert);
				final AudioManager audioManager = (AudioManager) context
						.getSystemService(Context.AUDIO_SERVICE);
				if (audioManager.getStreamVolume(AudioManager.STREAM_ALARM) != 0) {
					mMediaPlayer.setAudioStreamType(AudioManager.STREAM_ALARM);
					mMediaPlayer.prepare();
					mMediaPlayer.start();
				}
			} catch (IOException e) {
				System.out.println("OOPS");
			}
		}

		// Get an alarm sound. Try for an alarm. If none set, try notification,
		// Otherwise, ringtone.
		private Uri getAlarmUri() {
			Uri alert = RingtoneManager
					.getDefaultUri(RingtoneManager.TYPE_ALARM);
			if (alert == null) {
				alert = RingtoneManager
						.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
				if (alert == null) {
					alert = RingtoneManager
							.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
				}
			}
			return alert;
		}

	}

	// Current location overlay to draw blue dot
	public class CurrentLocOverlay extends com.google.android.maps.Overlay {
		public boolean draw(Canvas canvas, MapView mapView, boolean shadow,
				long when) {
			super.draw(canvas, mapView, shadow);

			Point screenPts = new Point();
			mapView.getProjection().toPixels(currentPos, screenPts);

			Bitmap bmp = BitmapFactory.decodeResource(getResources(),
					R.drawable.blue_dot);
			canvas.drawBitmap(bmp, screenPts.x - (bmp.getWidth() / 2),
					screenPts.y - (bmp.getHeight() / 2), null);

			return true;
		}
	}

	// checks if device has gps so it doesn't break the emulator
	private boolean hasGPSDevice(Context context) {
		if (!triedGPS) {
			triedGPS = true;
			gps = false;
			locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
			if (locationManager != null) {
				List<String> providers = locationManager.getAllProviders();
				if (providers != null) {
					if (providers.contains(LocationManager.GPS_PROVIDER)) {
						if (locationManager
								.getLastKnownLocation(LocationManager.GPS_PROVIDER) != null) {
							gps = true;
						}
					}
				}
			}
		}

		return gps;
	}

	// Overlay which handles the alarm locations
	@SuppressWarnings("rawtypes")
	class AlarmLocationOverlay extends ItemizedOverlay {
		private List<AlarmOverlayItem> items = new ArrayList<AlarmOverlayItem>();

		public AlarmLocationOverlay(Drawable defaultMarker) {
			super(defaultMarker);
			boundCenterBottom(defaultMarker);
			populate();
		}

		// remove the ith location and update
		public void remove(int i) {
			items.remove(i);
			setLastFocusedIndex(-1);
			populate();
		}

		// add an AlarmOverlayItem and update
		public void addItem(GeoPoint p, String title, double r, boolean am) {
			AlarmOverlayItem newItem = new AlarmOverlayItem(getID(), p, title,
					r, am);
			items.add(newItem);
			setLastFocusedIndex(-1);
			populate();
		}

		// find an unused id for a primary key
		private int getID() {
			int result = 0;
			boolean available = false;

			while (!available) {
				available = true;
				for (int i = 0; i < items.size() && available; i++) {
					if (items.get(i).getID() == result) {
						available = false;
						result++;
					}
				}
			}

			return result;
		}

		// add item from last session, already has id, and update
		public void addItem(int id, GeoPoint p, String title, double r,
				boolean am) {
			AlarmOverlayItem newItem = new AlarmOverlayItem(id, p, title, r, am);
			items.add(newItem);
			setLastFocusedIndex(-1);
			populate();
		}

		// returns the ith location
		@Override
		protected AlarmOverlayItem createItem(int i) {
			return items.get(i);

		}

		// returns number of alarm locations
		@Override
		public int size() {
			return (items.size());
		}

		public void draw(Canvas canvas, MapView mapView, boolean shadow) {
			super.draw(canvas, mapView, shadow);

		}

		// add location if mark is true
		@Override
		public boolean onTouchEvent(MotionEvent event, MapView mv) {
			if (event.getAction() == 1 && mark) {
				gp = mv.getProjection().fromPixels((int) event.getX(),
						(int) event.getY());

				// clear dialog fields
				title.setText("");
				range.setText("");
				alarmBox.setChecked(false);
				// delete is only for edit
				delete.setVisibility(View.GONE);

				// get alarm information
				dialog.show();
				return true;
			}
			return false; // nothing happened
		}

		// edit ith location if edit is true
		@Override
		protected boolean onTap(int i) {
			if (edit) {
				AlarmOverlayItem item = items.get(i);
				tap_int = i;

				// get fields of ith location
				title.setText(item.getTitle());
				range.setText("" + item.getRange());
				alarmBox.setChecked(item.getAlarm());
				delete.setVisibility(View.VISIBLE);

				dialog.show();
				return true;
			}
			return (false); // nothing happened
		}

	}
}
